
<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />

    <title>Leo’s Console Gui &#8212; Leo 6.7.2 documentation</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
    <link rel="stylesheet" type="text/css" href="_static/classic.css" />
    <link rel="stylesheet" type="text/css" href="_static/custom.css" />
    
    <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
    <script src="_static/jquery.js"></script>
    <script src="_static/underscore.js"></script>
    <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
    <script src="_static/doctools.js"></script>
    <script src="_static/sphinx_highlight.js"></script>
    
    <script src="_static/sidebar.js"></script>
    
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="next" title="A Miscellany of Leo Scripting" href="scripting-miscellany.html" />
    <link rel="prev" title="Debugging with Leo" href="debuggers.html" /> 
  </head><body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="scripting-miscellany.html" title="A Miscellany of Leo Scripting"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="debuggers.html" title="Debugging with Leo"
             accesskey="P">previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="leo_toc.html">Leo 6.7.2 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="intermediatetopics.html" accesskey="U">Advanced Topics</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Leo’s Console Gui</a></li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <section id="leo-s-console-gui">
<h1>Leo’s Console Gui<a class="headerlink" href="#leo-s-console-gui" title="Permalink to this heading">¶</a></h1>
<p>This chapter describes Leo’s console gui. This allows Leo to be run remotely.</p>
<div class="contents local topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><p><a class="reference internal" href="#system-requirements" id="id1">System requirements</a></p></li>
<li><p><a class="reference internal" href="#starting-leo-with-the-console-gui" id="id2">Starting Leo with the console gui</a></p></li>
<li><p><a class="reference internal" href="#exiting-leo-saving-files" id="id3">Exiting Leo &amp; saving files</a></p></li>
<li><p><a class="reference internal" href="#navigation-and-editing" id="id4">Navigation and editing</a></p></li>
<li><p><a class="reference internal" href="#leo-key-bindings" id="id5">Leo key bindings</a></p></li>
<li><p><a class="reference internal" href="#limitations" id="id6">Limitations</a></p>
<ul>
<li><p><a class="reference internal" href="#curses-limitations" id="id7">Curses limitations</a></p></li>
<li><p><a class="reference internal" href="#npyscreen-limitations" id="id8">npyscreen limitations</a></p></li>
<li><p><a class="reference internal" href="#unfixed-bugs" id="id9">Unfixed bugs</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#broadcasting-and-listening" id="id10">Broadcasting and listening</a></p></li>
<li><p><a class="reference internal" href="#developing-the-cursesgui2-plugin" id="id11">Developing the cursesGui2 plugin</a></p>
<ul>
<li><p><a class="reference internal" href="#tracing-is-essential" id="id12">Tracing is essential</a></p></li>
<li><p><a class="reference internal" href="#noteworthy-functions-and-methods" id="id13">Noteworthy functions and methods</a></p></li>
<li><p><a class="reference internal" href="#running-unit-tests" id="id14">Running unit tests</a></p></li>
</ul>
</li>
</ul>
</div>
<p>Here is a screen shot:</p>
<p><img alt="ConsoleWindow" src="_images/console-window.png" /></p>
<p>The area between colons in the Tree pane corresponds to Leo’s icon box:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">+</span><span class="p">:</span>    <span class="p">:</span> <span class="n">node</span> <span class="n">has</span> <span class="n">unexpanded</span> <span class="n">children</span><span class="o">.</span>
<span class="o">-</span><span class="p">:</span>    <span class="p">:</span> <span class="n">node</span> <span class="ow">is</span> <span class="n">expanded</span><span class="o">.</span>
 <span class="p">:</span>    <span class="p">:</span> <span class="n">node</span> <span class="n">has</span> <span class="n">no</span> <span class="n">children</span><span class="o">.</span>
 <span class="s1">&#39;*   : node is the selected node.</span>
 <span class="p">:</span> <span class="n">C</span>  <span class="p">:</span> <span class="n">node</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">clone</span><span class="o">.</span>
 <span class="p">:</span>  <span class="n">M</span> <span class="p">:</span> <span class="n">node</span> <span class="ow">is</span> <span class="n">marked</span><span class="o">.</span>
 <span class="p">:</span>   <span class="n">T</span><span class="p">:</span> <span class="n">node</span> <span class="n">has</span> <span class="n">body</span> <span class="n">text</span><span class="o">.</span>
</pre></div>
</div>
<section id="system-requirements">
<h2><a class="toc-backref" href="#id1">System requirements</a><a class="headerlink" href="#system-requirements" title="Permalink to this heading">¶</a></h2>
<p>Leo’s Console minimal dependencies are:</p>
<ul class="simple">
<li><p>For windows, install windows-curses with <cite>pip install windows-curses</cite>.</p></li>
<li><p>PythonTk for clipboard handling
For Linux use your system package manager, e.g. <cite>sudo apt install python-tk</cite>.</p></li>
</ul>
</section>
<section id="starting-leo-with-the-console-gui">
<h2><a class="toc-backref" href="#id2">Starting Leo with the console gui</a><a class="headerlink" href="#starting-leo-with-the-console-gui" title="Permalink to this heading">¶</a></h2>
<ol class="arabic">
<li><p>Resize your console/terminal to a recommended minimum size of 100x35.
<strong>Leo will crash on startup if there are fewer than 34 rows</strong>.</p></li>
<li><p>Launch Leo with the <code class="docutils literal notranslate"><span class="pre">--gui=console</span></code> command-line option:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span><span class="n">launchleo</span><span class="o">.</span><span class="n">py</span> <span class="o">--</span><span class="n">gui</span><span class="o">=</span><span class="n">console</span> <span class="p">[</span><span class="n">path</span> <span class="n">to</span> <span class="n">leo</span> <span class="n">file</span>\<span class="n">file_name</span><span class="o">.</span><span class="n">leo</span><span class="p">]</span>
</pre></div>
</div>
</li>
</ol>
<p>If no .leo file is given, Leo will open ~/.leo/workbook.leo (Leo’s workbook file). Initially, this file contains Leo’s cheat sheet and an example from the rst3 tutorial.</p>
<p><strong>Only one outline can be open at a time</strong>. The only way to load .leo files is from the command line. (There are no menus).</p>
</section>
<section id="exiting-leo-saving-files">
<h2><a class="toc-backref" href="#id3">Exiting Leo &amp; saving files</a><a class="headerlink" href="#exiting-leo-saving-files" title="Permalink to this heading">¶</a></h2>
<p>To exit Leo: click “Quit Leo” button and &lt;Enter&gt;. Ctrl-Q also works. <strong>There is no way to cancel Ctrl-Q</strong>. A dialog box will appear. Press Enter to select “No”. Press arrow keys to move between “Yes” and “No”. “Yes” saves, then exits. “No” Exits without saving.</p>
</section>
<section id="navigation-and-editing">
<h2><a class="toc-backref" href="#id4">Navigation and editing</a><a class="headerlink" href="#navigation-and-editing" title="Permalink to this heading">¶</a></h2>
<p>Moving around the main window:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Mouse</span> <span class="n">clicks</span> <span class="n">properly</span> <span class="n">switch</span> <span class="n">nodes</span><span class="o">.</span>
<span class="n">Arrow</span><span class="o">-</span><span class="n">up</span> <span class="ow">and</span> <span class="n">Arrow</span><span class="o">-</span><span class="n">down</span> <span class="n">keys</span> <span class="n">switch</span> <span class="n">panes</span> <span class="p">(</span><span class="n">when</span> <span class="ow">not</span> <span class="n">editing</span><span class="p">)</span><span class="o">.</span>
<span class="n">Tab</span><span class="p">:</span> <span class="n">moves</span> <span class="n">down</span> <span class="kn">from</span> <span class="nn">pane</span> <span class="n">to</span> <span class="n">pane</span><span class="o">.</span>
<span class="n">Shift</span><span class="o">-</span><span class="n">Tab</span><span class="p">:</span> <span class="n">moves</span> <span class="n">up</span> <span class="kn">from</span> <span class="nn">pane</span> <span class="n">to</span> <span class="n">pane</span><span class="o">.</span>
</pre></div>
</div>
<p>To edit a headline, select the node you wish to edit, then press e to edit the node headline (return to end):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">i</span><span class="p">:</span> <span class="n">to</span> <span class="n">insert</span> <span class="n">a</span> <span class="n">new</span> <span class="n">node</span><span class="o">.</span>
<span class="n">d</span><span class="p">:</span>  <span class="n">delete</span> <span class="n">node</span>
</pre></div>
</div>
<p>To edit body text, use Tab to move down to the Body Pane, or Shift-Tab to move up to the Body Pane. Follow the prompts:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">e</span> <span class="n">to</span> <span class="n">edit</span> <span class="n">line</span> <span class="p">(</span><span class="k">return</span> <span class="n">to</span> <span class="n">start</span> <span class="n">a</span> <span class="n">new</span> <span class="n">line</span><span class="p">)</span>
<span class="n">esc</span> <span class="n">to</span> <span class="n">end</span> <span class="n">editing</span><span class="o">.</span>
<span class="n">d</span> <span class="n">to</span> <span class="n">delete</span> <span class="n">line</span><span class="o">.</span>
</pre></div>
</div>
</section>
<section id="leo-key-bindings">
<h2><a class="toc-backref" href="#id5">Leo key bindings</a><a class="headerlink" href="#leo-key-bindings" title="Permalink to this heading">¶</a></h2>
<p>Supported Ctrl commands:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Ctrl</span><span class="o">-</span><span class="n">B</span> <span class="p">(</span><span class="n">execute</span><span class="o">-</span><span class="n">script</span><span class="p">)</span><span class="o">.</span>
<span class="n">Ctrl</span><span class="o">-</span><span class="n">F</span> <span class="p">(</span><span class="n">find</span><span class="p">)</span>
<span class="n">Ctrl</span><span class="o">-</span><span class="n">Q</span> <span class="p">(</span><span class="n">quit</span><span class="o">-</span><span class="n">leo</span><span class="p">)</span>
<span class="n">Ctrl</span><span class="o">-</span><span class="n">S</span> <span class="p">(</span><span class="n">save</span><span class="p">)</span> <span class="n">Works</span> <span class="k">for</span> <span class="n">windows</span> <span class="n">cmd</span><span class="o">.</span><span class="n">exe</span><span class="p">,</span> <span class="n">but</span> <span class="ow">not</span> <span class="n">Consolez</span><span class="o">.</span>
</pre></div>
</div>
<p>Unsupported Ctrl commands:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Alt</span><span class="o">-</span><span class="n">S</span><span class="p">,</span>
<span class="n">Ctrl</span><span class="o">-</span><span class="n">Shift</span><span class="o">-</span><span class="n">S</span>
<span class="n">Ctrl</span><span class="o">-</span><span class="n">O</span>
<span class="n">Shift</span> <span class="n">arrows</span>
</pre></div>
</div>
</section>
<section id="limitations">
<h2><a class="toc-backref" href="#id6">Limitations</a><a class="headerlink" href="#limitations" title="Permalink to this heading">¶</a></h2>
<p>This plugin suffers from fundamental limitations, as discussed in the following sections…</p>
<section id="curses-limitations">
<h3><a class="toc-backref" href="#id7">Curses limitations</a><a class="headerlink" href="#curses-limitations" title="Permalink to this heading">¶</a></h3>
<p><strong>The curses module supports only simple control characters</strong>. Ctrl-S will work, Alt-S, Ctrl-Shift-S etc. will not. These limitations can not be fixed.</p>
</section>
<section id="npyscreen-limitations">
<h3><a class="toc-backref" href="#id8">npyscreen limitations</a><a class="headerlink" href="#npyscreen-limitations" title="Permalink to this heading">¶</a></h3>
<p>The npyscreen package defines widgets with limited capabilities:</p>
<ul>
<li><p><strong>npyscreen does not support selection ranges in text</strong>!</p></li>
<li><p>Shift arrows are not supported, because there are no selection ranges.</p></li>
<li><p>Cut/paste is theoretically supported, but in the absence of selections
only paste might work. And paste may work only in limited contexts…</p></li>
<li><p>Editing the log or body pane is a bit strange. You switch between tabs
with tab or shift-tab. Type ‘e’ to edit edit mode, as shown on the
on-screen prompts.</p>
<p>Edit mode defines a <em>range</em> of lines that are being edited. Hitting
return extends the range. Initially, the range consists of a single line,
with the cursor at the end of the line. Moving outside the range with
up/down arrow keys ends editing. Doing a more Leonine job would require a
complete rewrite of the base classes.</p>
</li>
<li><p>Deleting a line is not possible in edit mode. Use ‘d’ outside of edit
mode to delete a line in the log or body panes.</p></li>
<li><p>The body text is not syntax colored.</p></li>
</ul>
</section>
<section id="unfixed-bugs">
<h3><a class="toc-backref" href="#id9">Unfixed bugs</a><a class="headerlink" href="#unfixed-bugs" title="Permalink to this heading">¶</a></h3>
<p>The following bugs have resisted serious efforts to fix them. I will work on them further only if they cause <em>serious</em> difficulties to those who use the console gui.</p>
<ul class="simple">
<li><p>Shifting focus to the minibuffer after Ctrl-F works initially, but thereafter Tab and Shift-Tab don’t work as expected until all widgets have been visited.  A workaround is to navigate to the minibuffer <em>before</em> using Ctrl-F, but this is not a perfect fix either.</p></li>
<li><p>After startup, the output from g.es correctly goes to the log widget, but it is scrolled out of view!</p></li>
</ul>
</section>
</section>
<section id="broadcasting-and-listening">
<h2><a class="toc-backref" href="#id10">Broadcasting and listening</a><a class="headerlink" href="#broadcasting-and-listening" title="Permalink to this heading">¶</a></h2>
<p>The console gui sends the output of g.pr and g.trace to another console. To do this, you must start a socket listener in the <em>other</em> console, listening to the broadcaster on localhost:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Leo</span> <span class="n">Qt</span> <span class="p">(</span><span class="n">listener</span><span class="p">)</span> <span class="o">&lt;--</span> <span class="n">Leo</span> <span class="n">console</span><span class="p">,</span> <span class="p">(</span><span class="n">broadcaster</span><span class="p">)</span>
</pre></div>
</div>
<p>To set this up:</p>
<ol class="arabic simple">
<li><p>In the <strong>listener console</strong>, start a regular Leo Qt session with the <code class="docutils literal notranslate"><span class="pre">--listen-to-log</span></code> command-line option. You can start a listener at any time with Leo’s <code class="docutils literal notranslate"><span class="pre">listen-to-log</span></code> command. The <code class="docutils literal notranslate"><span class="pre">kill-log-listener</span></code> command kills the listener, if it exists.</p></li>
<li><p>In the <strong>broadcast console</strong>, start Leo with the console gui using the <code class="docutils literal notranslate"><span class="pre">--gui=console</span></code> command-line option. This automatically starts the broadcaster.</p></li>
</ol>
<p>If the listener is active, the log output from the curses gui console will be displayed in the listener’s console.</p>
</section>
<section id="developing-the-cursesgui2-plugin">
<h2><a class="toc-backref" href="#id11">Developing the cursesGui2 plugin</a><a class="headerlink" href="#developing-the-cursesgui2-plugin" title="Permalink to this heading">¶</a></h2>
<p>The following sections discuss will be of interest <em>only</em> to those who want to enhance the cursesGui2.py plugin. All others can safely ignore this discussion.</p>
<p>The post: <a class="reference external" href="https://groups.google.com/forum/#!topic/npyscreen/nk2pjj71bok">Debugging npyscreen apps using two consoles</a> discusses the strategy used to bootstrap this plugin. It’s easier to develop now that so much is working, but developing this code will always be difficult.</p>
<p>The console gui code stands “between” the npyscreen code and Leo’s core code. With only very minor exceptions, <strong>Leo’s core and the npyscreen code must remain completely unchanged</strong>.  Thus, the console gui wraps just about everything. This makes the plugin’s code inherently complex, but this complexity can not be helped.</p>
<p><strong>Important</strong>: It would pointless to describe the code in detail. Devs must come up to speed on their own by studying traces. Don’t even <em>think</em> of trying to remember details. Instead, use cff to study the code.</p>
<section id="tracing-is-essential">
<h3><a class="toc-backref" href="#id12">Tracing is essential</a><a class="headerlink" href="#tracing-is-essential" title="Permalink to this heading">¶</a></h3>
<p>You <em>can not</em> use g.pdb to debug cursesGui2.py, for two reasons:</p>
<ul class="simple">
<li><p>g.pdb’s output would overwrite the screen.
Writing to the second console would not help because…</p></li>
<li><p>There would be no way to get input to pdb.</p></li>
</ul>
<p>As a result, <strong>devs must uses traces</strong> to figure out what is happening. The
<a class="reference external" href="console-gui.html#broadcasting-and-listening">Broadcasting and listing</a>
section tells how to send traces to a <em>second</em> console. Use only g.pr and g.trace to create traces. <strong>Do not use print statements in cursesGui2.py</strong>.</p>
</section>
<section id="noteworthy-functions-and-methods">
<h3><a class="toc-backref" href="#id13">Noteworthy functions and methods</a><a class="headerlink" href="#noteworthy-functions-and-methods" title="Permalink to this heading">¶</a></h3>
<p>The following methods contain crucial traces:</p>
<ul class="simple">
<li><p><strong>IH.handle_input</strong> (external/npyscreen/wgwidget.py) shows the raw input to npyscreen.</p></li>
<li><p><strong>k.masterKeyHandler</strong> (leoKeys.py) shows the keys passed to Leo’s core.</p></li>
<li><p><strong>k.masterCommand</strong> (leoKeys.py) shows the Leo command (if any) bound to the raw key.</p></li>
</ul>
<p>Other noteworthy methods and functions, all in cursesGui2.py:</p>
<ul class="simple">
<li><p><strong>CGui.createCursesTop</strong> creates the main window by calling a helper for each part of the main window. The helpers handle the <em>extremely complex</em> details of setting and/or injecting ivars into various classes. Getting these ivars right is the heart of the plugin.</p></li>
<li><p><strong>LeoMiniBuffer.h_return</strong> contains a crucial hack that allows the minibuffer to be used both to enter commands and to enter find strings.</p></li>
<li><p>The top-level <strong>es, pr and trace functions</strong> replace g.es, g.pr and g.trace functions so that they send their results to the second console.</p></li>
<li><p><strong>CGui.monkeyPatch</strong> contains some hacks needed to make the ‘start-find’ command work.</p></li>
</ul>
<p>To enable tracing for these methods, and many others, set the trace variable at the start of the method.  Feel free to add your own traces in consoleGui2.py.</p>
</section>
<section id="running-unit-tests">
<h3><a class="toc-backref" href="#id14">Running unit tests</a><a class="headerlink" href="#running-unit-tests" title="Permalink to this heading">¶</a></h3>
<p><strong>F4 runs all unit tests</strong>. IH.handle_input binds F4 as a special case. All unit tests presently pass when run from the console gui. Devs <em>must</em> run all tests in the console gui before committing any changes to this plugin.</p>
</section>
</section>
</section>


            <div class="clearer"></div>
          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
            <p class="logo"><a href="leo_toc.html">
              <img class="logo" src="_static/LeoLogo.svg" alt="Logo"/>
            </a></p>
  <div>
    <h4>Previous topic</h4>
    <p class="topless"><a href="debuggers.html"
                          title="previous chapter">Debugging with Leo</a></p>
  </div>
  <div>
    <h4>Next topic</h4>
    <p class="topless"><a href="scripting-miscellany.html"
                          title="next chapter">A Miscellany of Leo Scripting</a></p>
  </div>
<div id="searchbox" style="display: none" role="search">
  <h3 id="searchlabel">Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
      <input type="submit" value="Go" />
    </form>
    </div>
</div>
<script>document.getElementById('searchbox').style.display = "block"</script>
        </div>
<div id="sidebarbutton" title="Collapse sidebar">
<span>«</span>
</div>

      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="scripting-miscellany.html" title="A Miscellany of Leo Scripting"
             >next</a> |</li>
        <li class="right" >
          <a href="debuggers.html" title="Debugging with Leo"
             >previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="leo_toc.html">Leo 6.7.2 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="intermediatetopics.html" >Advanced Topics</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Leo’s Console Gui</a></li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
        &#169; Copyright 1997-2023, Edward K. Ream.
      Last updated on February 28, 2023.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 5.3.0.
    </div>
  </body>
</html>